package com.lwei.ljpro.dao.impl;

import com.lwei.ljpro.dao.IBaseDao;
import com.lwei.ljpro.util.BeanUtil;
import com.lwei.ljpro.util.SnowFlake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Repository;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

@Repository
public class BaseDaoImpl<T> implements IBaseDao<T> {

    private Logger logger = LoggerFactory.getLogger("baseDaoImpl");

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public T findOneById(String key, Long id) {
        ValueOperations<String, T> valueOperations = redisTemplate.opsForValue();
        return valueOperations.get(key + id);
    }

    @Override
    public Boolean saveById(String key, Long id, T t) {
        ValueOperations<String, T> valueOperations = redisTemplate.opsForValue();
        //正常保存

        //利用反射将id赋值
        try {
            Method setId  = t.getClass().getMethod("setId", Long.class);
            setId.invoke(t,id);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            logger.error("保存失败, 反射异常", e);
            return false;
        }

        //TODO 加一个事务或回滚
        valueOperations.set(key + id, t);

        //再用一个list维护对象列表
        ListOperations listOperations = redisTemplate.opsForList();
        try {
            listOperations.rightPush(key, id);
        } catch (Exception e){
            logger.error("保存对象时维护中间表异常", e);
            return false;
        }
        return true;
    }

    /**
     *设置 key 的值为 value
     *如果key不存在添加key 保存值为value
     *如果key存在则对value进行覆盖
     */
    @Override
    public Long save(String key, T t) {
        //没有id则随机生成
        SnowFlake snowFlake = SnowFlake.instance();
        Long id = snowFlake.nextId();
        //正常保存
        Boolean save = saveById(key, id, t);
        if(save){
            return id;
        } else {
            return null;
        }
    }

    /**
     * 设置key的值为value 并返回旧值。 如果key不存在返回为null
     * @param key 不能为null
     */
    @Override
    public T update(String key, Long id, T t) {
        //先查询再修改,确保不修改id
        T one = findOneById(key, id);
        if(one != null){
            T o = (T) BeanUtil.combineSydwCore(t, one);
            ValueOperations<String, T> valueOperations = redisTemplate.opsForValue();
            return valueOperations.getAndSet(key + id, o);
        }else{
            return null;
        }

    }

    @Override
    public void delete(String key, Long id) throws NullPointerException{
        ValueOperations<String, T> valueOperations = redisTemplate.opsForValue();
        if(valueOperations.size(key + id) > 0){
            redisTemplate.delete(key + id);
            //将维护列表中的值删除
            ListOperations listOperations = redisTemplate.opsForList();
            listOperations.remove(key, 1, id);
        }else {
            throw new NullPointerException("删除对象不存在");
        }
    }

    @Override
    public List<T> listEntryAll(String key) {
        List<T> valueList = new ArrayList<T>();
        ListOperations listOperations = redisTemplate.opsForList();
        //获取key对应的所以id
        List<Long> list = listOperations.range(key, 0, -1);
        if(list.size() >0 ){
            ValueOperations<String, T> valueOperations = redisTemplate.opsForValue();
            for (Long id : list) {
                T t = valueOperations.get(key + id);
                valueList.add(t);
            }
        }
        return valueList;
    }
}
